package eu.vranckaert.calendar.util;

import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import eu.vranckaert.calendar.widget.BlockView;
import eu.vranckaert.calendar.widget.BlocksLayout;
import eu.vranckaert.calendar.widget.ObservableScrollView;
import eu.vranckaert.calendar.widget.Workspace;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * User: Dirk Vranckaert
 * Date: 20/02/13
 * Time: 14:52
 */
public abstract class CalendarView implements Workspace.OnViewChangedListener, ObservableScrollView.OnScrollListener {
    protected Activity context;
    protected static final int CURRENT_INDEX = 2;
    protected Workspace workspace;
    protected List<Data> mData = new ArrayList<Data>();

    private int scrollY = -1;
    private OnDataLoadListener onDataLoadListener;
    private OnTimeBlockClickListener onTimeBlockClickListener;
    private List<Integer> blockColorResIds;
    private int defaultBlockColorResId = -1;

    protected CalendarView(Activity context, Workspace workspace, int blockColorResId) {
        this.workspace = workspace;
        this.context = context;
        this.defaultBlockColorResId = blockColorResId;
        workspace.setOnViewChangedListener(this);
    }

    protected class Data {
        private ViewGroup rootView;
        private ObservableScrollView scrollView;
        private View nowView;
        private BlocksLayout blocksView;

        public ViewGroup getRootView() {
            return rootView;
        }

        public void setRootView(ViewGroup rootView) {
            this.rootView = rootView;
        }

        public ObservableScrollView getScrollView() {
            return scrollView;
        }

        public void setScrollView(ObservableScrollView scrollView) {
            this.scrollView = scrollView;
        }

        public View getNowView() {
            return nowView;
        }

        public void setNowView(View nowView) {
            this.nowView = nowView;
        }

        public BlocksLayout getBlocksView() {
            return blocksView;
        }

        public void setBlocksView(BlocksLayout blocksView) {
            this.blocksView = blocksView;
        }
    }

    protected void displayBlockViews(Data data, List<? extends TimeBlock> timeBlocks, int column) {
        for (TimeBlock timeBlock : timeBlocks) {
            int blockColorResId = defaultBlockColorResId;

            if (blockColorResIds != null && !blockColorResIds.isEmpty() && blockColorResIds.size() > column) {
                blockColorResId = blockColorResIds.get(column);
            }

            Date endTime = timeBlock.getTimeBlockEndTime();
            if (endTime == null) {
                Calendar cal = Calendar.getInstance();
                cal.setTime(timeBlock.getTimeBlockStartTime());
                cal.set(Calendar.HOUR_OF_DAY, cal.getActualMaximum(Calendar.HOUR_OF_DAY));
                cal.set(Calendar.MINUTE, cal.getActualMaximum(Calendar.MINUTE));
                cal.set(Calendar.SECOND, cal.getActualMaximum(Calendar.SECOND));
                cal.set(Calendar.MILLISECOND, cal.getActualMaximum(Calendar.MILLISECOND));
                endTime = cal.getTime();
            }

            BlockView blockView = new BlockView(
                    context,
                    timeBlock.getTimeBlockId(),
                    timeBlock.getTimeBlockTitle(),
                    timeBlock.getTimeBlockStartTime().getTime(),
                    endTime.getTime(),
                    column,
                    blockColorResId
            );
            blockView.setTextSize(10);
            if (timeBlock.getTimeBlockId() != null) {
                blockView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        BlockView clickedBlockView = (BlockView) view;
                        if (getOnTimeBlockClickListener() != null) {
                            getOnTimeBlockClickListener().onTimeBlockClicked(clickedBlockView.getBlockId());
                        }
                    }
                });
            }
            data.getBlocksView().addBlock(blockView);
        }
    }

    public interface OnDataLoadListener {
        List<? extends TimeBlock> loadDataForDay(Date day);
    }

    public interface OnTimeBlockClickListener {
        void onTimeBlockClicked(Object id);
    }

    @Override
    public void onScrollChanged(ObservableScrollView view) {
        // Keep each day view at the same vertical scroll offset.
        scrollY = view.getScrollY();
        scrollAllScrollViews();
    }

    @Override
    public void onViewChanged(int index) {
        workspace.setCurrentScreenFast(CURRENT_INDEX);
        scrollAllScrollViews();
    }

    /* ABSTRACT METHODS */
    protected abstract void setupFirstFiveViews(Date date);
    protected abstract boolean updateNowView(boolean forceScroll);
    public abstract Date getCurrentDate();
    public abstract void reloadDataForDay(Date date);
    public abstract void reloadAllData();

    /* GETTERS AND SETTERS */

    public void setOnDataLoadListener(OnDataLoadListener onDataLoadListener) {
        this.onDataLoadListener = onDataLoadListener;
    }

    public void setOnTimeBlockClickListener(OnTimeBlockClickListener onTimeBlockClickListener) {
        this.onTimeBlockClickListener = onTimeBlockClickListener;
    }

    public OnDataLoadListener getOnDataLoadListener() {
        return onDataLoadListener;
    }

    public OnTimeBlockClickListener getOnTimeBlockClickListener() {
        return onTimeBlockClickListener;
    }

    private void scrollAllScrollViews() {
        if (scrollY == -1)
            return;

        for (Data data : mData) {
            data.getScrollView().scrollTo(0, scrollY);
        }
    }

    public void scrollAllScrollViewsTo(int scrollY) {
        if (scrollY == -1)
            return;

        for (Data data : mData) {
            data.getScrollView().scrollTo(0, scrollY);
        }
    }

    public void setBlockColorResIds(List<Integer> blockColorResIds) {
        this.blockColorResIds = blockColorResIds;
    }
}
